package ldh.maker.db;

import ldh.database.Column;
import ldh.database.Table;
import ldh.maker.database.TableInfo;
import ldh.maker.util.DbUtil;
import ldh.maker.util.UiUtil;
import ldh.maker.vo.TreeNode;
import org.apache.commons.dbutils.QueryRunner;

import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Created by ldh on 2017/3/29.
 */
public class PojoDb {

    public static boolean loadData(TreeNode treeNode, String dbName, Table table) throws SQLException {
        Connection connection = UiUtil.H2CONN;
        boolean isLoadColumns = false;
        String sql = "select * from pojo where tree_node_id = ? and db_name = ? and table_name = ?";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setInt(1, treeNode.getId());
        statement.setString(2, dbName);
        statement.setString(3, table.getName());
        ResultSet rs = statement.executeQuery();
        if(rs.next()){
            table.setJavaName(rs.getString("name"));
            table.setId(rs.getInt("id"));
            table.setText(rs.getString("text"));
            isLoadColumns = true;
        }
        statement.close();

        if (isLoadColumns) {
            loadColumnData(treeNode, table);

            PojoFunctionDb.loadData(treeNode, table);

            return true;
        }
        return false;
    }

    public static boolean loadDatas(TreeNode treeNode, String dbName, TableInfo tableInfo) throws SQLException {
        Map<String, Map<String, Object>> tableMap = new HashMap<>();
        Connection connection = UiUtil.H2CONN;
        boolean isLoadColumns = false;
        String sql = "select * from pojo where tree_node_id = ? and db_name = ?";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setInt(1, treeNode.getId());
        statement.setString(2, dbName);
        ResultSet rs = statement.executeQuery();
        while(rs.next()){
            Map map = new HashMap();
            map.put("name", rs.getString("name"));
            map.put("id", rs.getInt("id"));
            isLoadColumns = true;
        }
        statement.close();

        if (isLoadColumns) {
            Map<Long, Map<String, Object>> columnsMap = loadColumnDatas(treeNode);
            for(Map.Entry<String, Map<String, Object>> entry : tableMap.entrySet()) {
                String tableName = entry.getKey();
                Table table = tableInfo.getTable(tableName);
                table.setId((Integer) entry.getValue().get("id"));
                table.setJavaName((String) entry.getValue().get("name"));

                Map<String, Object> columMap = columnsMap.get(table.getId());
                Column column = getColumn(table, (String) columMap.get("columName"));
                column.setProperty((String) columMap.get("name"));
                column.setJavaType((Class<?>) columMap.get("javaType"));

//                PojoFunctionDb.loadData(treeNode, table);
            }
            return tableMap.size() == tableInfo.getTables().size();
        }
        return false;
    }

    public static Map<Long, Map<String, Object>> loadColumnDatas(TreeNode treeNode) throws SQLException {
        Map<Long, Map<String, Object>> columnsMap = new HashMap<>();
        Connection connection = UiUtil.H2CONN;
        String sql = "select * from pojo_filed where tree_node_id = ?";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setInt(1, treeNode.getId());
        ResultSet rs = statement.executeQuery();
        while(rs.next()){
            Map<String, Object> map = new HashMap<>();
            map.put("columnName", rs.getString("column_name"));
            map.put("name", rs.getString("name"));
            map.put("javaType", DbUtil.javaClass(rs.getString("java_type")));
            columnsMap.put(rs.getLong("pojo_id"), map);
        }
        statement.close();
        return columnsMap;
    }

    public static Table loadColumnData(TreeNode treeNode, Table table) throws SQLException {
        Table data = null;
        Connection connection = UiUtil.H2CONN;
        String sql = "select * from pojo_filed where tree_node_id = ? and pojo_id = ?";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setInt(1, treeNode.getId());
        statement.setInt(2, table.getId());
        ResultSet rs = statement.executeQuery();
        while(rs.next()){
            String columnName = rs.getString("column_name");
            Column column = getColumn(table, columnName);
            if(column == null) continue;
            column.setProperty(rs.getString("name"));
            column.setText(rs.getString("text"));
            column.setJavaType(DbUtil.javaClass(rs.getString("java_type")));
        }
        statement.close();
        return data;
    }

    private static Column getColumn(Table table, String columnName) {
        for (Column column : table.getColumnList()) {
            if (column.getName().equals(columnName)) {
                return column;
            }
        }
        return null;
    }

    public static void saveOrUpdate(String db, Table table, int treeNodeId) throws SQLException {
        if (table.getId() == null) {
            savePojo(db, table, treeNodeId);
            PojoFunctionDb.saveData(treeNodeId, table);
//            EnumDb.save(treeNodeId, table);
        } else {
            updatePojo(db, table, treeNodeId);
            PojoFunctionDb.deleteData(treeNodeId, table);
            PojoFunctionDb.saveData(treeNodeId, table);
//            EnumDb.update(treeNodeId, table);
        }
    }

    public static int savePojo(String db, Table table, int treeNodeId) throws SQLException {
        Connection connection = UiUtil.H2CONN;
        String sql = "insert into pojo(table_name, name, text, db_name, tree_node_id) values(?, ?, ?, ?, ?)";
        PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
        statement.setString(1, table.getName());
        statement.setString(2, table.getJavaName());
        statement.setString(3, table.getText());
        statement.setString(4, db);
        statement.setInt(5, treeNodeId);
        statement.executeUpdate();
        ResultSet rs = statement.getGeneratedKeys();
        int id = -1;
        if(rs.next()){
            id = rs.getInt(1);
        }
        statement.close();
        table.setId(id);

        saveColumnNames(table.getColumnList(), id, treeNodeId);
        return id;
    }

    public static void saveColumnNames(List<Column> columns, int pojoId, int treeNodeId) throws SQLException {
        Connection connection = UiUtil.H2CONN;
        String sql = "insert into pojo_filed(column_name, name, text, java_type, pojo_id, tree_node_id) values(?, ?, ?, ?, ?, ?)";
        PreparedStatement statement = connection.prepareStatement(sql);
        for (Column column : columns) {
            statement.setString(1, column.getName());
            statement.setString(2, column.getProperty());
            statement.setString(3, column.getText());
            statement.setString(4, column.getJavaType());
            statement.setInt(5, pojoId);
            statement.setInt(6, treeNodeId);
            statement.addBatch();
        }
        statement.executeBatch();
        statement.close();
    }

    public static void updatePojo(String db, Table table, int treeNodeId) throws SQLException {
        Connection connection = UiUtil.H2CONN;
        String sql = "update pojo set name = ?, text = ? where tree_node_id = ? and db_name = ? and table_name = ?";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setString(1, table.getJavaName());
        statement.setString(2, table.getText());
        statement.setInt(3, treeNodeId);
        statement.setString(4, db);
        statement.setString(5, table.getName());
        statement.executeUpdate();
        statement.close();

        updateColumnNames(table.getColumnList(), table.getId(), treeNodeId);
    }

    public static void updateColumnNames(List<Column> columns, int pojoId, int treeNodeId) throws SQLException {
        Connection connection = UiUtil.H2CONN;
        String sql = "update pojo_filed set name = ?, text = ?, java_type=? where pojo_id = ? and tree_node_id = ? and column_name=?";
        PreparedStatement statement = connection.prepareStatement(sql);
        for (Column column : columns) {
            int i=1;
            statement.setString(i++, column.getProperty());
            statement.setString(i++, column.getText());
            statement.setString(i++, column.getPropertyClass().getSimpleName());
            statement.setInt(i++, pojoId);
            statement.setInt(i++, treeNodeId);
            statement.setString(i++, column.getName());
            statement.addBatch();
        }
        statement.executeBatch();
        statement.close();
    }

    public static void delete(TreeNode treeNode) throws SQLException {
        Connection connection = UiUtil.H2CONN;
        QueryRunner queryRunner = new QueryRunner();
        String sql = "delete from pojo_filed where tree_node_id = ?";
        queryRunner.update(connection, sql, treeNode.getId());

        sql = "delete from pojo where tree_node_id = ?";
        queryRunner.update(connection, sql, treeNode.getId());
    }
}
